package com.foreveross.fetl.util;

import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
//import org.apache.commons.lang.ArrayUtils;

@SuppressWarnings({"rawtypes","unchecked"})
public class DBUtilsTemplate {  
	  
    private QueryRunner queryRunner;  
    @Resource
    private DataSource dataSource;
    
    public DBUtilsTemplate(Connection conn) {
    	if(queryRunner == null){
    		System.out.println("new queryRunner:"+ dataSource);
    		this.queryRunner = new QueryRunner(dataSource);
    	}
    }
  
    /** 
     *  
     * @param sql 
     *            插入sql语句 
     * @param params 
     *            插入参数 
     * @return 返回影响行数 
     * @throws SQLException 
     */  
    public int insert(String sql, Object[] params) throws SQLException {  
        int affectedRows = 0;  
        if (params == null) {  
            affectedRows = queryRunner.update(sql);
        } else {  
            affectedRows = queryRunner.update(sql, params);  
        }  
        return affectedRows;  
    }  
  
    /** 
     * 插入数据库，返回自动增长的主键 
     *  
     * @param sql - 
     *            执行的sql语句 
     * @return 主键 注意；此方法没关闭资源 
     * @throws SQLException 
     */  
    public int insertForKeys(String sql, Object[] params) throws SQLException {  
        int key = 0;  
        PreparedStatement stmt = null;  
        ResultSet rs = null;  
        try {  
            stmt = this.dataSource.getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);  
            ParameterMetaData pmd = stmt.getParameterMetaData();  
            if (params.length < pmd.getParameterCount()) {  
                throw new SQLException("参数错误:" + pmd.getParameterCount());  
            }  
            for (int i = 0; i < params.length; i++) {  
                stmt.setObject(i + 1, params[i]);  
            }  
            stmt.executeUpdate();  
            rs = stmt.getGeneratedKeys();  
            if (rs.next()) {  
                key = rs.getInt(1);  
            }  
        } catch (SQLException e) {  
        	throw new SQLException(e);
        } finally {  
            if (rs != null) { // 关闭记录集  
                try {  
                    rs.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            }  
            if (stmt != null) { // 关闭声明  
                try {  
                    stmt.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            }  
        }
        return key;  
    }  
    public long count(String sql, Object... params) throws SQLException {  
    	Long num = 0l;
        if (params == null) {  
            num = (Long) queryRunner.query(sql, new ScalarHandler());  
        } else {  
            num = (Long) queryRunner.query(sql, new ScalarHandler(), params);  
        }  
        return num==null?0:num;
    }  
  
    /** 
     * 单条修改记录 
     *  
     * @param sql 
     *            sql语句 
     * @param param 
     *            参数 
     * @return 受影响的行数 
     * @throws SQLException 
     */  
    public int update(String sql, Object param) throws SQLException {  
        return update(sql, new Object[] { param });  
    }  
  
    /** 
     * 单条修改记录 
     *  
     * @param sql 
     *            sql语句 
     * @param params 
     *            参数数组 
     * @return 受影响的行数 
     * @throws SQLException 
     */  
    public int update(String sql, Object[] params) throws SQLException {  
        int affectedRows = 0;  
	    if (params == null) {  
	        affectedRows = queryRunner.update(sql);  
	    } else {  
	        affectedRows = queryRunner.update(sql, params);  
	    }  
        return affectedRows;  
    }  
  
    /** 
     * 批量修改记录 
     *  
     * @param sql 
     *            sql语句 
     * @param params 
     *            二维参数数组 
     * @return 受影响的行数的数组 
     * @throws SQLException 
     */  
    public int[] batchUpdate(String sql, Object[][] params) throws SQLException {  
        int[] affectedRows = new int[0];  
        affectedRows = queryRunner.batch(sql, params);  
        return affectedRows;  
    }  
  
    /** 
     * 执行查询，将每行的结果保存到一个Map对象中，然后将所有Map对象保存到List中 
     *  
     * @param sql 
     *            sql语句 
     * @param param 
     *            参数 
     * @return 查询结果 
     * @throws SQLException 
     */  
    public List<Map<String, Object>> find(String sql, Object param) throws SQLException {  
        return find(sql, new Object[] { param });  
    }  
  
    /** 
     * 执行查询，将每行的结果保存到一个Map对象中，然后将所有Map对象保存到List中 
     *  
     * @param sql 
     *            sql语句 
     * @param params 
     *            参数数组 
     * @param index 从第几条开始取（不包括自己）
     * @param pagesize 取几条
     * @return 查询结果 
     * @throws SQLException 
     */  
    /*public void findPage(PageHelp<Map<String, Object>> page,String sql, int index, int pagesize, Object... params) throws SQLException {  
        List<Map<String, Object>> list = null;
        if (params == null) {
            list = (List<Map<String, Object>>) queryRunner.query(conn,sql+" LIMIT ?,?", new MapListHandler(), new Object[] { index,pagesize });  
        } else {
            list = (List<Map<String, Object>>) queryRunner.query(conn,sql+" LIMIT ?,?", new MapListHandler(), ArrayUtils.addAll(  
                    params, new Integer[] { index, pagesize }));
        }
        //select * from 
        long count = this.count("select count(1) "+sql.substring(sql.indexOf("from"), sql.length()), params);
        page.setTotalCount(count);page.setItems(list);list=null;params=null;
    }  */
  
    /** 
     * 执行查询，将每行的结果保存到一个Map对象中，然后将所有Map对象保存到List中 
     *  
     * @param sql 
     *            sql语句 
     * @param params 
     *            参数数组 
     * @return 查询结果 
     * @throws SQLException 
     */  
    public List<Map<String, Object>> find(String sql, Object[] params) throws SQLException {  
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();  
        if (params == null) {  
            list = (List<Map<String, Object>>) queryRunner.query(sql, new MapListHandler());  
        } else {  
            list = (List<Map<String, Object>>) queryRunner.query(sql, new MapListHandler(), params);  
        }  
        return list;  
    }  
  
    /** 
     * 执行查询，将每行的结果保存到Bean中，然后将所有Bean保存到List中 
     *  
     * @param entityClass 
     *            类名 
     * @param sql 
     *            sql语句 
     * @return 查询结果 
     * @throws SQLException 
     */  
    public <T> List<T> find(Class<T> entityClass, String sql) throws SQLException {  
        return find(entityClass, sql, null);  
    }  
  
    /** 
     * 执行查询，将每行的结果保存到Bean中，然后将所有Bean保存到List中 
     *  
     * @param entityClass 
     *            类名 
     * @param sql 
     *            sql语句 
     * @param param 
     *            参数 
     * @return 查询结果 
     * @throws SQLException 
     */  
    public <T> List<T> find(Class<T> entityClass, String sql, Object param) throws SQLException {  
        return find(entityClass, sql, new Object[] { param });  
    }  
  
    /** 
     * 执行查询，将每行的结果保存到Bean中，然后将所有Bean保存到List中 
     *  
     * @param entityClass 
     *            类名 
     * @param sql 
     *            sql语句 
     * @param params 
     *            参数数组 
     * @return 查询结果 
     * @throws SQLException 
     */  
    public <T> List<T> find(Class<T> entityClass, String sql, Object[] params) throws SQLException {  
        List<T> list = new ArrayList<T>();  
        if (params == null) {  
            list = (List<T>) queryRunner.query(sql, new BeanListHandler(entityClass));  
        } else {  
            list = (List<T>) queryRunner.query(sql, new BeanListHandler(entityClass), params);  
        }  
        return list;  
    }  
  
    /** 
     * 查询出结果集中的第一条记录，并封装成对象 
     *  
     * @param entityClass 
     *            类名 
     * @param sql 
     *            sql语句 
     * @return 对象 
     * @throws SQLException 
     */  
    public <T> T findFirst(Class<T> entityClass, String sql) throws SQLException {  
        return findFirst(entityClass, sql, null);  
    }  
  
    /** 
     * 查询出结果集中的第一条记录，并封装成对象 
     *  
     * @param entityClass 
     *            类名 
     * @param sql 
     *            sql语句 
     * @param param 
     *            参数 
     * @return 对象 
     * @throws SQLException 
     */  
    public <T> T findFirst(Class<T> entityClass, String sql, Object param) throws SQLException {  
        return findFirst(entityClass, sql, new Object[] { param });  
    }  
  
    /** 
     * 查询出结果集中的第一条记录，并封装成对象 
     *  
     * @param entityClass 
     *            类名 
     * @param sql 
     *            sql语句 
     * @param params 
     *            参数数组 
     * @return 对象 
     * @throws SQLException 
     */  
    public <T> T findFirst(Class<T> entityClass, String sql, Object[] params) throws SQLException {  
        Object object = null;  
        if (params == null) {  
            object = queryRunner.query(sql, new BeanHandler(entityClass));  
        } else {  
            object = queryRunner.query(sql, new BeanHandler(entityClass), params);  
        }  
        return (T) object;  
    }  
  
    /** 
     * 查询出结果集中的第一条记录，并封装成Map对象 
     *  
     * @param sql 
     *            sql语句 
     * @return 封装为Map的对象 
     * @throws SQLException 
     */  
    public Map<String, Object> findFirst(String sql) throws SQLException {  
        return findFirst(sql, null);  
    }  
  
    /** 
     * 查询出结果集中的第一条记录，并封装成Map对象 
     *  
     * @param sql 
     *            sql语句 
     * @param param 
     *            参数 
     * @return 封装为Map的对象 
     * @throws SQLException 
     */  
    public Map<String, Object> findFirst(String sql, Object param) throws SQLException {  
        return findFirst(sql, new Object[] { param });  
    }  
  
    /** 
     * 查询出结果集中的第一条记录，并封装成Map对象 
     *  
     * @param sql 
     *            sql语句 
     * @param params 
     *            参数数组 
     * @return 封装为Map的对象 
     * @throws SQLException 
     */  
    public Map<String, Object> findFirst(String sql, Object[] params) throws SQLException {  
        Map<String, Object> map = null;  
        if (params == null) {  
            map = (Map<String, Object>) queryRunner.query(sql, new MapHandler());  
        } else {  
            map = (Map<String, Object>) queryRunner.query(sql, new MapHandler(), params);  
        }  
        return map;  
    }  
  
  
    /** 
     * 查询某一条记录，并将指定列的数据转换为Object 
     *  
     * @param sql 
     *            sql语句 
     * @param columnName 
     *            列名 
     * @param param 
     *            参数 
     * @return 结果对象 
     * @throws SQLException 
     */  
    public Object findBy(String sql, String columnName, Object param) throws SQLException {  
        return findBy(sql, columnName, new Object[] { param });  
    }  
  
    /** 
     * 查询某一条记录，并将指定列的数据转换为Object 
     *  
     * @param sql 
     *            sql语句 
     * @param columnName 
     *            列名 
     * @param params 
     *            参数数组 
     * @return 结果对象 
     * @throws SQLException 
     */  
	public Object findBy(String sql, String columnName, Object[] params) throws SQLException {  
        Object object = null;  
        if (params == null) {  
            object = queryRunner.query(sql, new ScalarHandler(columnName));  
        } else {  
            object = queryRunner.query(sql, new ScalarHandler(columnName), params);  
        }  
        return object;  
    }  
  
  
    /** 
     * 查询某一条记录，并将指定列的数据转换为Object 
     *  
     * @param sql 
     *            sql语句 
     * @param columnIndex 
     *            列索引 
     * @param param 
     *            参数 
     * @return 结果对象 
     * @throws SQLException 
     */  
    public Object findBy(String sql, int columnIndex, Object param) throws SQLException {  
        return findBy(sql, columnIndex, new Object[] { param });  
    }  
  
    /** 
     * 查询某一条记录，并将指定列的数据转换为Object 
     *  
     * @param sql 
     *            sql语句 
     * @param columnIndex 
     *            列索引 
     * @param params 
     *            参数数组 
     * @return 结果对象 
     * @throws SQLException 
     */  
    public Object findBy(String sql, int columnIndex, Object[] params) throws SQLException {  
        Object object = null;  
        if (params == null) {  
            object = queryRunner.query(sql, new ScalarHandler(columnIndex));  
        } else {  
            object = queryRunner.query(sql, new ScalarHandler(columnIndex), params);  
        }  
        return object;  
    }  
  
    /** 
     *  
     * @param <T>分页查询 
     * @param beanClass 
     * @param sql 
     * @param index 从第几条取（不包括本身）
     * @param pageSize 取几条
     * @param params 
     * @return 
     * @throws SQLException 
     */
   /* public <T> void findPage(PageHelp<T> page,Class<T> beanClass, String sql, int index, int pageSize, Object... params) throws SQLException {
    	List<T> list = query(beanClass, sql + " LIMIT ?,?", ArrayUtils.addAll(params, new Integer[] { index, pageSize }));
        long count = this.count("select count(1) "+sql.substring(sql.indexOf("from"), sql.length()), params);
        page.setTotalCount(count);page.setItems(list);
    }  */
  
    public <T> List<T> query(Class<T> beanClass, String sql, Object... params) throws SQLException {  
        return (List<T>) queryRunner.query(sql, new BeanListHandler(beanClass), params);  
    } 
}  